# @Author:黄景涛
# @Date: 2023/10/9
from functools import wraps
from faker import Faker
from datetime import datetime
from utils.yaml_util import read_yaml

cfg_info = read_yaml()

fk = Faker(locale='zh_CN')

""" 组织架构 """
# 一级组织配置
group_organizate_name = cfg_info.get('usermanager').get('organization_prefix_name') + str(
    datetime.now().strftime('%m%d')) + '_' + str(datetime.timestamp(datetime.now())).split('.')[0]

# 二级组织配置
two_organizate_names = ['二级组织', ]

# 三级组织配置
three_organizate_names = ['三级组织', ]

# 叶子、非叶子组织下的用户数量
_USER_COUNT = _USER_LIMIT = cfg_info.get('usermanager').get('user_limit')


class Node:
    """组织: 以链表形式存储"""

    def __init__(self, name):
        """
        :param name: 组织架构树的根节点，虚拟节点
        :user_limit: 组织下，已挂载人员数量
        :unused_limit: 组织下，剩余可挂载人员数量
        :id: 组织id
        :parent: 父级组织id
        :childrens: 子级组织id列表
        """
        self.name = name
        self.user_limit = _USER_COUNT
        self.id = None
        self.parent = None
        self.childrens = []


# 构造链表：组织架构的n叉树
def create_organization():
    # 创建虚拟的根节点
    root_node = Node('root')

    # 创建集团
    group_node = Node(group_organizate_name)
    group_node.parent = root_node
    root_node.childrens.append(group_node)

    for one in two_organizate_names:
        # 创建一级组织节点
        one_node = Node(one)
        # 一级组织的父节点属性
        one_node.parent = group_node
        # 将一级组织节点，添加到根节点的childrens属性中
        group_node.childrens.append(one_node)
        for two in three_organizate_names:
            # 创建二级组织节点
            two_node = Node(two)
            two_node.parent = one_node
            one_node.childrens.append(two_node)
            two_node.user_limit = _USER_LIMIT
    #  返回链表的根节点
    return root_node


# 统计函数调用次数
def count_calls(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """
        类只存在一个，推导可得，类属性不受实例个数影响，也只存在一个，可视为类层级上的全局变量。
        所以，每次wrapper实例化，num_calls都是一个全局变量，可达到值累计效果
        """
        wrapper.num_calls += 1
        func(*args, **kwargs)

    """
    只在装饰时初始化一次，赋值为0
    函数的一等对象特性：当作类对象看待，给函数添加类属性num_calls
    """
    wrapper.num_calls = 0
    return wrapper


# DFS遍历
@count_calls
def dfs(current_node: Node, depth=0):
    if not current_node:
        return

    # 遍历当前节点
    msg = f'\t' * depth + f'层级：{depth}\t组织名称：{current_node.name}\t人员数量：{current_node.user_limit}\t组织id：{current_node.id}\t子组织：{[c.name for c in current_node.childrens]}'
    if current_node.name != "root":
        msg += f'\t父组织：{current_node.parent.name}'
    print(msg)
    # 遍历子节点
    for child in current_node.childrens:
        dfs(child, depth + 1)


if __name__ == '__main__':
    root = create_organization()
    counts = 0
    dfs(root)
    print(f'总数：{dfs.num_calls}')
